package com.panlin.printer;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import com.panlin.printer.bean.Result;
import com.panlin.printer.utils.BitmapUtils;
import com.panlin.printer.utils.CodeUtils;
import com.panling.printapi.MdUtils;
import com.panling.printapi.Printer;
import com.panling.printapi.StringUtility;


//打印工具返回
public class PrintModule {
    public static final String TAG = "PrintModule";
    public static final int speed = 200;
    public static final String UNI_KEY_CONTENT="content";
    public static final String UNI_KEY_WIDTH="width";
    public static final String UNI_KEY_INTERVAL="interval";
    public static final String UNI_KEY_HEIGHT="height";
    public static final String UNI_KEY_CHARSET_NAME="charsetName";

    private final int maxWidth = 380;
    private final int maxHeight = 480;

    private final int defaultInterval = 30;

    
    public void init() {
        try {
            Log.d(TAG, "init start");
            boolean success = Printer.getInstance().init();
            if (success) {
                Log.d(TAG, "init success");
                Printer.getInstance().open(false);
                Printer.getInstance().setPrintSpeed(speed);
            }
        } catch (Exception e) {
            Log.d(TAG, "init start error:"+e.getMessage());
        }
    }

    public void free() {
        Printer.getInstance().free();
        Log.e(TAG, "free");
    }

    public void initPrint() {
        Printer.getInstance().initPrint();
        Log.e(TAG, "initPrint");
    }

    public void Feed_to_Next() {
        Printer.getInstance().Feed_to_Next();
        Log.e(TAG, "Feed_to_Next");
    }

    public void Black_label_On() {
        Printer.getInstance().Black_label_On();
        Log.e(TAG, "Black_label_On");
    }

    public void Black_label_Off() {
        Printer.getInstance().Black_label_Off();
        Log.e(TAG, "Black_label_Off");
    }

    
    public void sendData(JSONObject options) {
        String content =  options.getString(UNI_KEY_CONTENT);
        if(!TextUtils.isEmpty(content)){
            int code = Printer.getInstance().sendData(content.getBytes());
        }
    }

    
    public void printText(JSONObject options) {
        String content = options.getString(UNI_KEY_CONTENT);
        String charsetName = options.getString(UNI_KEY_CHARSET_NAME);
        if(!TextUtils.isEmpty(content)){
            Log.e(TAG, "printText:"+content+" ,charsetName:"+charsetName);
            if(!TextUtils.isEmpty(charsetName)){
                Printer.getInstance().printText(content, charsetName);
            }else {
                Printer.getInstance().printText(content, "gbk");
            }
        }
    }

     
    public void print(JSONObject options) {
        String base64 = options.getString(UNI_KEY_CONTENT);
        if (base64 == null || base64.isEmpty()) return;
        int mode = options.getIntValue("mode");
        int interval = options.getIntValue("interval");
        if(interval<=10){
            interval = 30;
        }
        byte[] bytes = Base64.decode(removeHeaderFromBase64(base64), Base64.DEFAULT);
        Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.length),380,480,true);
        if(bitmap!=null){
            Printer.getInstance().printImage3(bitmap, interval);
        }
        Log.e(TAG, "print");
    }


    private String removeHeaderFromBase64(String base64String) {
        int commaIndex = base64String.indexOf(",");
        if (commaIndex != -1) {
            return base64String.substring(commaIndex + 1);
        } else {
            return base64String;
        }
    }


     
    public void printImage(JSONObject options) {
        String base64 = options.getString(UNI_KEY_CONTENT);
        if (base64 == null || base64.isEmpty()) return;

        try {
            int requireWidth = maxWidth;
            int requireHeight = maxHeight;
            int requireInterval = defaultInterval;
            int width = options.getIntValue(UNI_KEY_WIDTH);
            int height = options.getIntValue(UNI_KEY_HEIGHT);
            if(width!=0){
                requireWidth = Math.min(width,maxWidth);
            }
            if(height!=0){
                requireHeight = Math.min(height,maxHeight);
            }
            int interval = options.getIntValue(UNI_KEY_INTERVAL);
            if(interval!=0){
                if(interval<=5){
                    interval = 5;
                }else if(interval>=100){
                    interval = 100;
                }
                requireInterval = interval;
            }
            byte[] bytes = Base64.decode(removeHeaderFromBase64(base64), Base64.DEFAULT);
            Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.length),
                    requireWidth, requireHeight,true);
            Bitmap blackBitmap = BitmapUtils.convertToBlackAndWhite(bitmap);
            if(blackBitmap!=null){
                Log.d(TAG, "printImage requireInterval:"+requireInterval);
                Printer.getInstance().printImage3(blackBitmap,requireInterval);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    
    public void printBarcode(JSONObject options) {
        String barcodeData = options.getString(UNI_KEY_CONTENT);
        String barcodeType = options.getString("barcodeType");
        if (barcodeData != null && !barcodeData.isEmpty() && !barcodeData.trim().isEmpty()) {
            Printer.BarcodeType type = Printer.BarcodeType.valueOf(barcodeType);
            Log.d(TAG, "printBarcode barcodeData:" + barcodeData+" ,barcodeType:"+barcodeType);
            int barcodeTypeValue = 6;
            byte[] data = barcodeData.getBytes();
            int length = data.length;
            if (type == Printer.BarcodeType.UPC_A) {
                if (length == 11 && StringUtility.isDecimal(barcodeData)) {
                    barcodeTypeValue = 0;
                } else {
                    Log.e(TAG, "不是有效数据！有效数据规则:字符数11,只能输入0~9的数字");
                }
            } else if (type == Printer.BarcodeType.JAN8_EAN8) {
                if (length == 7 && StringUtility.isDecimal(barcodeData)) {
                    barcodeTypeValue = 1;
                } else {
                    Log.e(TAG, "不是有效数据！有效数据规则:字符数7,只能输入0~9的数字");
                }
            } else if (type == Printer.BarcodeType.JAN13_EAN13) {
                if (length == 12 && StringUtility.isDecimal(barcodeData)) {
                    barcodeTypeValue = 2;
                } else {
                    Log.e(TAG, "不是有效数据！有效数据规则:字符数12,只能输入0~9的数字");
                }
            } else if (type == Printer.BarcodeType.CODE39) {
                for (byte b : data) {
                    int d = b & 0xFF;
                    if ((d >= 48 && d <= 57) || (d >= 65 && d <= 90) || d == 32 || d == 36 || d == 37 || (d >= 42 && d <= 47 && d != 44)) {
                        barcodeTypeValue = 3;
                    } else {
                        Log.e(TAG, "不是有效数据！有效数据规则:字符数1~24,范围0~9、A~Z、空、$、%、+、-、。、/");
                    }
                }
            } else if (type == Printer.BarcodeType.ITF_Interleaved_2_of_5) {
                if (length >= 2 && length <= 255 && length % 2 == 0 && StringUtility.isDecimal(barcodeData)) {
                    barcodeTypeValue = 4;
                } else {
                    Log.e(TAG, "输入长度只能为小于等于24位数字的偶数,范围0~9");
                }
            } else if (type == Printer.BarcodeType.CODE128) {
                if (length >= 1 && length <= 255) {
                    for (byte b : data) {
                        int d = b & 0xFF;
                        if ((d < 0 || d > 127) && (d < 193 || d > 196)) {
                            Log.e(TAG, "不是有效数据！");
                        }
                    }
                    barcodeTypeValue = 5;
                } else {
                    Log.e(TAG, "输入长度只能为1~30位字符，不包括汉字");
                }
            }
            Log.d(TAG, "printBarcode barcodeType:" + barcodeTypeValue);
            try {
                switch (barcodeTypeValue) {
                    case 0:
                        Printer.getInstance().printBarcode(barcodeData, Printer.BarcodeType.UPC_A);
                        break;
                    case 1:
                        Printer.getInstance().printBarcode(barcodeData, Printer.BarcodeType.JAN8_EAN8);
                        break;
                    case 2:
                        Printer.getInstance().printBarcode(barcodeData, Printer.BarcodeType.JAN13_EAN13);
                        break;
                    case 3:
                        Printer.getInstance().printBarcode(barcodeData, Printer.BarcodeType.CODE39);
                        break;
                    case 4:
                        Printer.getInstance().printBarcode(barcodeData, Printer.BarcodeType.ITF_Interleaved_2_of_5);
                        break;
                    case 5:
                        Printer.getInstance().printBarcode(barcodeData, Printer.BarcodeType.CODE128);
                        break;
                    case 6:
                        Log.d(TAG, "Printer.BarcodeType.QR_CODE====" + barcodeData);
                        Bitmap bitmap = CodeUtils.generateBitmap(barcodeData, 320, 320);
                        Printer.getInstance().printImage(bitmap);
                        break;
                }
            } catch (Exception e) {
                Log.d(TAG, "printBarcode error--------" + e.getMessage());
            }
        }
    }

     
    public void setFeedRow(int type, int n) {
        Printer.getInstance().setFeedRow(type, n);
        Log.e(TAG, "setFeedRow type:"+type+" ,n:"+n);
    }

     
    public void setGSPMode(int x, int y) {
        Printer.getInstance().setGSPMode(x, y);
        Log.e(TAG, "setGSPMode x:"+x+" ,y:"+y);
    }

     
    public void setPrintRowSpacing(int spacing) {
        Printer.getInstance().setPrintRowSpacing(spacing);
        Log.e(TAG, "setPrintRowSpacing:"+spacing);
    }

     
    public void setPrintLeftMargin(int nl, int nh) {
        Printer.getInstance().setPrintLeftMargin(nl, nh);
        Log.e(TAG, "setPrintLeftMargin nl:"+nl+" ,nh:"+nh);
    }

     
    public void setPrintAlignmentMode(int n) {
        Printer.getInstance().setPrintAlignmentMode(n);
        Log.e(TAG, "setPrintAlignmentMode n:"+n);
    }

     
    public void setPrintSpeed(int speed) {
        Printer.getInstance().setPrintSpeed(speed);
        Log.e(TAG, "setPrintSpeed :"+speed);
    }

     
    public void setPrintChromaLevel(int chroma) {
        Printer.getInstance().setPrintChromaLevel(chroma);
        Log.e(TAG, "setPrintChromaLevel :"+chroma);
    }

     
    public void restoreDefault() {
        Printer.getInstance().restoreDefault();
        Log.e(TAG, "restoreDefault :");
    }

     
    public void setBarcodeHeight(int height) {
        Printer.getInstance().setBarcodeHeight(height);
        Log.e(TAG, "setBarcodeHeight :"+height);
    }

     
    public void setBarcodeWidth(int width) {
        Printer.getInstance().setBarcodeWidth(width);
        Log.e(TAG, "setBarcodeWidth :"+width);
    }

     
    public void setBarcodeHRI(int position) {
        Printer.getInstance().setBarcodeHRI(position);
        Log.e(TAG, "setBarcodeHRI :"+position);
    }

     
    public void setUnderlineMode(int n) {
        Printer.getInstance().setUnderlineMode(n);
        Log.e(TAG, "setUnderlineMode :"+n);
    }

     
    public void setBoldMode(int n) {
        Printer.getInstance().setBoldMode(n);
        Log.e(TAG, "setBoldMode :"+n);
    }

     
    public void setFontDimension(int n) {
        Printer.getInstance().setFontDimension(n);
        Log.e(TAG, "setFontDimension :"+n);
    }

    
    public void Restore_factory(int n) {
        Printer.getInstance().Restore_factory(n);
        Log.e(TAG, "Restore_factory :"+n);
    }


    public JSONObject getBaudRate() {
        String baudRate = Printer.getInstance().getBaudRate();
        Log.e(TAG, "getBaudRate :"+baudRate);
        return Result.makeResult("baudRate",baudRate);
    }


    public JSONObject getVersion() {
        String version = Printer.getInstance().getVersion();
        Log.e(TAG, "getVersion :"+version);
        return Result.makeResult("version",version);
    }

    public JSONObject getFontVersion() {
        String fontVersion = Printer.getInstance().getFontVersion();
        Log.e(TAG, "getFontVersion :"+fontVersion);
        return Result.makeResult("fontVersion",fontVersion);
    }

    public Bitmap rangeBitmap(byte[] decodedBytes) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length, options);

        options.inSampleSize = calculateInSampleSize(options, 380, 490);
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length, options);
    }

    private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int height = options.outHeight;
        int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            int heightRatio = (int) Math.ceil((float) height / (float) reqHeight);
            int widthRatio = (int) Math.ceil((float) width / (float) reqWidth);
            inSampleSize = Math.min(heightRatio, widthRatio);
        }

        return inSampleSize;
    }
}
